package com.cssl.config;

import com.cssl.pojo.Users;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.cache.RedisCacheWriter;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import java.time.Duration;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by tym on 2024/2/27 0027.
 * Redis缓存配置类
 */
@Configuration
public class RedisConfig extends CachingConfigurerSupport {

    //缓存管理器
    @Primary
    @Bean
    public CacheManager cacheManager1(RedisConnectionFactory factory) {
        RedisCacheManager cacheManager = RedisCacheManager.create(factory);
        return cacheManager;
    }
    @Bean
    public CacheManager cacheManager2(RedisConnectionFactory factory) {
        //改序列化方式为json
        ObjectMapper om = new ObjectMapper();
        om.registerModule(new JavaTimeModule());  //支持JDK LocalDate
        //不加时间会写成[2025,4,17]而不是2025-04-17
        om.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.activateDefaultTyping(LaissezFaireSubTypeValidator.instance ,
                ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
        Jackson2JsonRedisSerializer<Object> serializer = new Jackson2JsonRedisSerializer<Object>(om,Object.class);

        //设置缓存配置
        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig();

        RedisCacheConfiguration config1 = config.serializeValuesWith(
                RedisSerializationContext.SerializationPair.fromSerializer(serializer))
                .entryTtl(Duration.ofSeconds(300))    //缓存时间,秒
                .disableCachingNullValues()           //不缓存空值
                .prefixCacheNameWith("users");        //前缀user+#id(userssss2)

        RedisCacheConfiguration config2 = config.serializeValuesWith(
                RedisSerializationContext.SerializationPair.fromSerializer(serializer))
                .entryTtl(Duration.ofHours(1))      //缓存时间,小时
                .disableCachingNullValues()        
                .prefixCacheNameWith("news");      

        //对每个缓存空间应用不同的配置
        Map<String, RedisCacheConfiguration> configMap = new HashMap<>();
        configMap.put("users", config1);            //users匹配@Cacheable的value属性值users
        configMap.put("news", config2);

        //初始化一个RedisCacheWriter
        RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(factory);

        //初始化RedisCacheManager
        RedisCacheManager cacheManager = new RedisCacheManager(redisCacheWriter, config, configMap);
        return cacheManager;
    }

    //对于自定义Users类需要注入，默认注入的是Object
    /*@Bean
    public RedisTemplate<String, Users> getRedisTemplate(RedisConnectionFactory factory) {
        RedisTemplate<String, Users> redisTemplate = new RedisTemplate<String, Users>();
        redisTemplate.setConnectionFactory(factory);
        return redisTemplate;
    }*/

    @Bean
    public RedisTemplate<String, Object> getRedisTemplate(RedisConnectionFactory factory) {
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<String, Object>();
        redisTemplate.setConnectionFactory(factory);
        redisTemplate.setKeySerializer(new StringRedisSerializer()); // key的序列化类型

        //改序列化方式为json
        ObjectMapper om = new ObjectMapper();
        om.registerModule(new JavaTimeModule());  //支持JDK LocalDate
        //不加时间会写成[2025,4,17]而不是2025-04-17
        om.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.activateDefaultTyping(LaissezFaireSubTypeValidator.instance ,
                ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);

        Jackson2JsonRedisSerializer json = new Jackson2JsonRedisSerializer(om,Object.class);
        redisTemplate.setValueSerializer(json); // value的序列化类型
        return redisTemplate;
    }
}
